-- @preview-file on clear

-- CombatCoreSystem.lua
-- 战斗核心系统：处理Spine骨骼碰撞检测、伤害计算等

local CombatCoreSystem = {}
CombatCoreSystem.__index = CombatCoreSystem

function CombatCoreSystem.new()
    local instance = {
        -- 碰撞检测组
        collisionGroups = {
            player = 1,
            enemy = 2,
            projectile = 3
        },
        
        -- 攻击命中框配置
        hitBoxes = {},
        
        -- 伤害计算
        damageRegistry = {},
        
        -- 敌人监视器
        enemyMonitors = {},
        
        -- 调试模式
        debugMode = true,
        showHitBoxes = false,
        
        -- 帧计时器
        frameTime = 0
    }
    
    return setmetatable(instance, CombatCoreSystem)
end

-- 注册攻击命中框
function CombatCoreSystem:registerHitBox(ownerId, hitBoxName, positions, damage, duration)
    local hitBox = {
        ownerId = ownerId,
        name = hitBoxName,
        positions = positions,  -- 骨骼位置表
        damage = damage,
        startTime = self.frameTime,
        duration = duration or 0.5,  -- 默认持续0.5秒
        isActive = true
    }
    
    if not self.hitBoxes[ownerId] then
        self.hitBoxes[ownerId] = {}
    end
    
    self.hitBoxes[ownerId][hitBoxName] = hitBox
    
    if self.debugMode then
        print(string.format("注册命中框: %s - %s, 伤害: %d, 持续时间: %.2f秒", 
            ownerId, hitBoxName, damage, duration or 0.5))
    end
    
    return hitBox
end

-- 获取Spine骨骼世界位置
function CombatCoreSystem:getBoneWorldPosition(spineNode, boneName, targetPosition)
    if not spineNode or not spineNode.findBone then
        return targetPosition
    end
    
    local bone = spineNode:findBone(boneName)
    if bone then
        -- 计算骨骼的世界坐标
        local boneX, boneY = bone:worldX(), bone:worldY()
        
        -- 考虑Spine节点的缩放和旋转
        local worldX = spineNode.x + boneX * spineNode.scaleX
        local worldY = spineNode.y + boneY * spineNode.scaleY
        
        if targetPosition then
            targetPosition.x = worldX
            targetPosition.y = worldY
        end
        
        return {x = worldX, y = worldY}
    end
    
    return targetPosition
end

-- 更新命中框位置（基于Spine骨骼）
function CombatCoreSystem:updateHitBoxPositions(ownerId, spineNode)
    local ownerHitBoxes = self.hitBoxes[ownerId]
    if not ownerHitBoxes or not spineNode then return end
    
    for hitBoxName, hitBox in pairs(ownerHitBoxes) do
        if hitBox.isActive then
            -- 更新所有骨骼位置
            for boneName, position in pairs(hitBox.positions) do
                self:getBoneWorldPosition(spineNode, boneName, position)
            end
            
            -- 检查是否超时
            if self.frameTime - hitBox.startTime > hitBox.duration then
                hitBox.isActive = false
                if self.debugMode then
                    print(string.format("命中框超时: %s - %s", ownerId, hitBoxName))
                end
            end
        end
    end
end

-- 检测碰撞
function CombatCoreSystem:checkCollision(attackerId, targetId, attackerSpine, targetSpine)
    local attackerHitBoxes = self.hitBoxes[attackerId]
    if not attackerHitBoxes or not targetSpine then return false, 0 end
    
    local totalDamage = 0
    local collisionDetected = false
    
    for hitBoxName, hitBox in pairs(attackerHitBoxes) do
        if hitBox.isActive then
            -- 获取攻击者的攻击框位置
            local attackPositions = {}
            for boneName, position in pairs(hitBox.positions) do
                if attackerSpine then
                    attackPositions[boneName] = self:getBoneWorldPosition(attackerSpine, boneName, {x = position.x, y = position.y})
                else
                    attackPositions[boneName] = position
                end
            end
            
            -- 获取目标的骨骼位置
            local targetBones = {}
            
            -- 剑士的主要骨骼
            if targetId:find("sword") then
                targetBones = {
                    "root", "body", "head", "weapon"
                }
            -- 弓箭手
            elseif targetId:find("archer") then
                targetBones = {
                    "root", "body", "head", "bow"
                }
            -- 刀兵
            elseif targetId:find("broadsword") then
                targetBones = {
                    "root", "body", "head", "weapon"
                }
            -- Boss
            elseif targetId:find("boss") then
                targetBones = {
                    "root", "body", "head", "weapon"
                }
            -- 玩家
            else
                targetBones = {
                    "root", "body", "head", "weapon"
                }
            end
            
            -- 检测碰撞
            for _, targetBone in ipairs(targetBones) do
                local targetPos = self:getBoneWorldPosition(targetSpine, targetBone, {x = 0, y = 0})
                if targetPos.x ~= 0 or targetPos.y ~= 0 then
                    -- 检查是否在攻击框内
                    for boneName, attackPos in pairs(attackPositions) do
                        if attackPos and targetPos then
                            local distance = math.sqrt(
                                (attackPos.x - targetPos.x) ^ 2 + 
                                (attackPos.y - targetPos.y) ^ 2
                            )
                            
                            -- 碰撞距离阈值
                            local collisionThreshold = 30
                            
                            if distance < collisionThreshold then
                                collisionDetected = true
                                totalDamage = totalDamage + hitBox.damage
                                
                                if self.debugMode then
                                    print(string.format("碰撞检测: %s 的 %s 命中 %s 的 %s, 距离: %.1f, 伤害: %d",
                                        attackerId, boneName, targetId, targetBone, distance, hitBox.damage))
                                end
                                
                                break
                            end
                        end
                    end
                    
                    if collisionDetected then break end
                end
            end
            
            if collisionDetected then break end
        end
    end
    
    return collisionDetected, totalDamage
end

-- 应用伤害
function CombatCoreSystem:applyDamage(targetId, damage, attackerId)
    -- 记录伤害
    if not self.damageRegistry[targetId] then
        self.damageRegistry[targetId] = {}
    end
    
    table.insert(self.damageRegistry[targetId], {
        damage = damage,
        attacker = attackerId,
        time = self.frameTime
    })
    
    if self.debugMode then
        print(string.format("应用伤害: %s 受到 %d 点伤害 (来自 %s)", 
            targetId, damage, attackerId or "未知"))
    end
    
    return true
end

-- 清除过期命中框
function CombatCoreSystem:cleanupExpiredHitBoxes()
    for ownerId, ownerHitBoxes in pairs(self.hitBoxes) do
        local toRemove = {}
        
        for hitBoxName, hitBox in pairs(ownerHitBoxes) do
            if not hitBox.isActive or (self.frameTime - hitBox.startTime > hitBox.duration * 2) then
                table.insert(toRemove, hitBoxName)
            end
        end
        
        for _, hitBoxName in ipairs(toRemove) do
            ownerHitBoxes[hitBoxName] = nil
        end
    end
end

-- 更新战斗系统
function CombatCoreSystem:update(dt)
    self.frameTime = self.frameTime + dt
    
    -- 清理过期命中框
    self:cleanupExpiredHitBoxes()
    
    -- 调试显示命中框
    if self.showHitBoxes then
        self:debugDrawHitBoxes()
    end
end

-- 调试绘制命中框
function CombatCoreSystem:debugDrawHitBoxes()
    -- 这里可以添加DrawNode来可视化命中框
    -- 由于DrawNode实现较复杂，这里只输出日志
    if self.debugMode and self.frameTime % 1 < 0.016 then  -- 每秒输出一次
        local activeCount = 0
        for _, ownerHitBoxes in pairs(self.hitBoxes) do
            for _, hitBox in pairs(ownerHitBoxes) do
                if hitBox.isActive then
                    activeCount = activeCount + 1
                end
            end
        end
        
        if activeCount > 0 then
            print(string.format("活跃命中框: %d 个", activeCount))
        end
    end
end

-- 重置战斗系统
function CombatCoreSystem:reset()
    self.hitBoxes = {}
    self.damageRegistry = {}
    self.frameTime = 0
    
    if self.debugMode then
        print("战斗系统已重置")
    end
end

return CombatCoreSystem